/**
 * 
 */
package co.edu.javeriana.ia.ga;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.math3.random.RandomData;
import org.apache.commons.math3.random.RandomDataImpl;
import org.jgap.Configuration;
import org.jgap.Gene;
import org.jgap.InvalidConfigurationException;

import co.edu.javeriana.ia.ga.readers.GenomeReader;

/**
 * <p>
 * Esta funcion permite crear los genes de un respectivo cromosoma. Los genes
 * representan cada uno de las reglas para los descriptores
 * </p>
 * 
 * @author <a href=f.triana@javeriana.edu.co">Alejandro Triana</a>
 * @version 1.0
 */
public class GenFactory {

	 /**
	 * <p>
	 * Crea el conjunto de genes para un cromosoma determinado. El idGenoma
	 * corresponde a la accion de la regla cuando todos se cumplen
	 * </p>
	 */
	public static Gene[] createGenes(Configuration conf)
			throws InvalidConfigurationException {

		Gene[] genes = new RuleGene[Constants.MAX_NUM_GENES];
		
		//Secuence genome = SecuenceReader.
		
		for (int i = 0; i < Constants.MAX_NUM_GENES; i++) {
			
			Genome genome = GenomeReader.instance.nextGenome();
			Map<String, Descriptor> descriptors = genome.getDescriptors();
			
			RuleGene gene = createGene(conf, genome, descriptors);
			
			genes[i] = gene;
		}

		return genes;
	}
	

	public static RuleGene createGene(Configuration conf, Genome genome, Map<String, Descriptor> descriptors)
			throws InvalidConfigurationException {
		
		RandomData ran = new RandomDataImpl();
		
		RuleAllele allele = new RuleAllele();
		Set<Entry<String, Descriptor>> desEntries =  descriptors.entrySet();
		
		Map<String, Descriptor> lstDescriptors = new TreeMap<String, Descriptor>();
		
		for (Entry<String, Descriptor> entryDes : desEntries) {
			
			Descriptor condition = new Descriptor();
			
			condition.setFrecuency(ran.nextInt(Constants.MIN_VALUE_FRECUENCY_DESCRIPTOR, Constants.MAX_VALUE_FRECUENCY_DESCRIPTOR));
			condition.setInternalId(entryDes.getValue().getInternalId());
			condition.setId(entryDes.getValue().getId());
			
			lstDescriptors.put(condition.getId(), condition);
		}
		// La accion de la regla corresponde al valor del genoma devuelto por la regla
		// Todas las acciones de un mismo cromosoma, tiene el mismo valor
		
		allele.setCondition(lstDescriptors);
		allele.setAction(genome);
		
		RuleGene gene = new RuleGene(conf, allele);
		return gene;
	}
}
